﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Cache;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Bigeagle.WPF.Controls
{
    /// <summary>
    /// 地图控件类
    /// </summary>
    public partial class MapControl : UserControl
    {
        #region 成员变量

        private static string WebClient_UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)";
        //private static string GoogleMapUrl = "http://mt{0}.google.cn/vt/lyrs=m@207000000,highlight:0x358fcd4735ab4f7f:0xd93a2e2370e1b364@1%7Cstyle:maps&hl=zh-CN&gl=CN&src=app&x={1}&y={2}&z={3}&s={4}" ;
        //private static string GoogleMapUrl = "http://emap{0}.is.autonavi.com/appmaptile?&server={0}&lyrs=aaa&hl=zh-CN&z={3}&x={1}&y={2}";
        private Point _LastPoint;

        /// <summary>
        /// 地图图片大小
        /// </summary>
        Size _MapImageSize;

        /// <summary>
        /// 地图缓存存放目录
        /// </summary>
        private string _MapCacheDirectory = string.Empty;

        /// <summary>
        /// 地图是否已载入
        /// </summary>
        private bool _IsMapLoaded = false;


        /// <summary>
        /// 要画的瓦片数组
        /// </summary>
        private List<DrawTileState> _States = new List<DrawTileState>();

        /// <summary>
        /// 图片缓存数组
        /// </summary>
        private Dictionary<string, Image> _MapCache = new Dictionary<string,Image>();

        /// <summary>
        /// 随机数
        /// </summary>
        /// <remarks>作为成员变量而不是临时变量存在是为了每次访问时产生相同的随机序列</remarks>
        Random _random = new Random((int)DateTime.Now.Ticks);

        /// <summary>
        /// google坐标系原点坐标
        /// </summary>
        private Point _GooglePoint;

        RequestCachePolicy _CachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable);


        #endregion//end 成员变量

        #region 依赖属性

        #region 坐标宽度

        public static readonly DependencyProperty ScaleWidthProperty =
    DependencyProperty.Register("ScaleWidth", typeof(double), typeof(MapControl)
    , new PropertyMetadata(30d, new PropertyChangedCallback(OnScaleWidthChanged)));

        public double ScaleWidth
        {
            get
            {
                return (double)GetValue(ScaleWidthProperty);
            }
            set
            {
                SetValue(ScaleWidthProperty, value);
            }
        }
        private static async void OnScaleWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MapControl control = (MapControl)d;
            control.gridMain.ColumnDefinitions[0].Width = new GridLength((double)e.NewValue);
            control.gridMain.RowDefinitions[1].Height = new GridLength((double)e.NewValue);
            if (control.IsLoaded)
            {
                await control.DrawBackgroundAsync();
            }
        }

        #endregion//end 坐标宽度

        #region 是否显示坐标

        public static readonly DependencyProperty IsShowScaleProperty =
    DependencyProperty.Register("IsShowScale", typeof(bool), typeof(MapControl)
    , new PropertyMetadata(true , new PropertyChangedCallback(OnIsShowScaleChanged)));

        public bool IsShowScale
        {
            get
            {
                return (bool)GetValue(IsShowScaleProperty);
            }
            set
            {
                SetValue(IsShowScaleProperty, value);
            }
        }
        private static async void OnIsShowScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MapControl control = (MapControl)d;
            if ((bool)e.NewValue)
            {
                control.gridMain.ColumnDefinitions[0].Width = new GridLength(control.ScaleWidth);
                control.gridMain.RowDefinitions[1].Height = new GridLength(control.ScaleWidth);
            }
            else
            {
                control.gridMain.ColumnDefinitions[0].Width = new GridLength(0);
                control.gridMain.RowDefinitions[1].Height = new GridLength(0);

            }
            if (control.IsLoaded)
            {
                await control.DrawBackgroundAsync();
            }
        }

        #endregion//end 是否显示坐标

        #region 坐标前景

        public static readonly DependencyProperty ScaleForegroundProperty =
    DependencyProperty.Register("ScaleForeground", typeof(Brush), typeof(MapControl)
    , new PropertyMetadata(new SolidColorBrush(Colors.Black), new PropertyChangedCallback(OnScaleForegroundChanged)));

        public Brush ScaleForeground
        {
            get
            {
                return (Brush)GetValue(ScaleForegroundProperty);
            }
            set
            {
                SetValue(ScaleForegroundProperty, value);
            }
        }
        private static async void OnScaleForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MapControl control = (MapControl)d;
            await control.DrawBackgroundAsync();

        }

        #endregion//end 坐标前景

        #region 坐标背景

        public static readonly DependencyProperty ScaleBackgroundProperty =
    DependencyProperty.Register("ScaleBackground", typeof(Brush), typeof(MapControl)
    , new PropertyMetadata(new SolidColorBrush(Colors.LightYellow), new PropertyChangedCallback(OnScaleBackgroundChanged)));

        public Brush ScaleBackground
        {
            get
            {
                return (Brush)GetValue(ScaleBackgroundProperty);
            }
            set
            {
                SetValue(ScaleBackgroundProperty, value);
            }
        }//end method

        private static async void OnScaleBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MapControl control = (MapControl)d;
            await control.DrawBackgroundAsync();
           
        }//end method

        #endregion//end 坐标背景

        #region 地图中心坐标点

        public static readonly DependencyProperty GeoCodeProperty =
    DependencyProperty.Register("GeoCode", typeof(Point), typeof(MapControl)
    , new PropertyMetadata(new Point(0,0), new PropertyChangedCallback(OnGeoCodeChanged)));

        public Point GeoCode
        {
            get
            {
                return (Point)GetValue(GeoCodeProperty);
            }
            set
            {
                SetValue(GeoCodeProperty, value);
            }
        }
        private async static void OnGeoCodeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MapControl control = (MapControl)d;
            if (control.IsLoaded)
            {
                await control.RefreshMapAsync();
            }

        }

        #endregion//end 地图中心坐标点

        #region 导航按钮点击每次移动的像素数

        public static readonly DependencyProperty MovePixelsProperty =
    DependencyProperty.Register("MovePixels", typeof(double), typeof(MapControl)
    , new PropertyMetadata(50d, new PropertyChangedCallback(OnMovePixelsChanged)));

        public double MovePixels
        {
            get
            {
                return (double)GetValue(MovePixelsProperty);
            }
            set
            {
                SetValue(MovePixelsProperty, value);
            }
        }
        private static void OnMovePixelsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion//end 导航按钮点击每次移动的像素数

        #region 地图缩放比例

        public static readonly DependencyProperty ZoomLevelProperty =
    DependencyProperty.Register("ZoomLevel", typeof(int), typeof(MapControl)
    , new PropertyMetadata(12, new PropertyChangedCallback(OnZoomLevelChanged)));

        public int ZoomLevel
        {
            get
            {
                return (int)GetValue(ZoomLevelProperty);
            }
            set
            {
                if (value > 1 && value <= 18)
                {
                    SetValue(ZoomLevelProperty, value);
                }
                else
                {
                    throw (new ArgumentException());
                }
            }
        }
        private static async void OnZoomLevelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MapControl control = (MapControl)d;
            control.sliderZoom.Value = control.ZoomLevel;
            if (control.IsLoaded)
            {
                await control.DrawBackgroundAsync();
                await control.RefreshMapAsync();
            }
        }

        #endregion//end 地图缩放比例

        #region 最大缓存瓦片数量

        public static readonly DependencyProperty MaxTileCacheCountProperty =
    DependencyProperty.Register("MaxTileCacheCount", typeof(int), typeof(MapControl)
    , new PropertyMetadata(100, new PropertyChangedCallback(OnMaxTileCacheCountChanged)));

        public int MaxTileCacheCount
        {
            get
            {
                return (int)GetValue(MaxTileCacheCountProperty);
            }
            set
            {
                SetValue(MaxTileCacheCountProperty, value);
            }
        }

        private static void OnMaxTileCacheCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MapControl control = (MapControl)d;
        }

        #endregion//end 最大缓存瓦片数量

        #region 地图类型

        public static readonly DependencyProperty MapStyleProperty =
    DependencyProperty.Register("MapStyle", typeof(GoogleMapStyles), typeof(MapControl)
    , new PropertyMetadata(GoogleMapStyles.RoadMap, new PropertyChangedCallback(OnMapStyleChanged))
    ,new ValidateValueCallback(OnMapStyleValidateValue));

        private static bool OnMapStyleValidateValue(object value)
        {
            GoogleMapStyles mapStyle = (GoogleMapStyles)value;
            return mapStyle == GoogleMapStyles.RoadMap
                || mapStyle == GoogleMapStyles.Satellite
                || mapStyle == GoogleMapStyles.Terrain
                || mapStyle == GoogleMapStyles.Treasure;
        }

        public GoogleMapStyles MapStyle
        {
            get
            {
                return (GoogleMapStyles)GetValue(MapStyleProperty);
            }
            set
            {
                SetValue(MapStyleProperty, value);
            }
        }
        private static async void OnMapStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MapControl control = (MapControl)d;
            //control.DrawBackgroundAsync();
            control.sliderZoom.Maximum = control.GetMaxZoomLevel((GoogleMapStyles)e.NewValue);
            if (control.IsLoaded)
            {
                await control.RefreshMapAsync();
            }

        }

        #endregion//end 地图缩放比例

        #region 图层集合
        public List<GoogleMapStyles> AdditionalLayers
        {
            get { return (List<GoogleMapStyles>)GetValue(AdditionalLayersProperty); }

        }
        // Using a DependencyProperty as the backing store for Items.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AdditionalLayersProperty =
            DependencyProperty.Register("AdditionalLayers", typeof(List<GoogleMapStyles>)
            , typeof(MapControl), new UIPropertyMetadata(new List<GoogleMapStyles>())
            , new ValidateValueCallback(OnAdditionalLayersValidateValue));

        private static bool OnAdditionalLayersValidateValue(object value)
        {
            List<GoogleMapStyles> layers = (List<GoogleMapStyles>)value;
            if (layers != null && layers.Count > 0)
            {
                
                GoogleMapStyles[] validateLayers = new GoogleMapStyles[] { GoogleMapStyles.Text, GoogleMapStyles.Traffic, GoogleMapStyles.Weather };
                return layers.Count(s => !validateLayers.Contains(s)) > 0;
            }
            else
            {
                //Console.WriteLine("null");
                return true;
            }
        }
        #endregion//end 图层集合

        #endregion//end 依赖属性

        private List<GoogleMapStyles> _ValidMapStyles = new List<GoogleMapStyles>();
        public List<GoogleMapStyles> ValidMapStyles
        {
            get
            {
                return _ValidMapStyles;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public MapControl()
        {
            InitializeComponent();
            SetValue(AdditionalLayersProperty, new List<GoogleMapStyles>());
            _MapCacheDirectory = string.Format("{0}\\GoogleTile", Directory.GetCurrentDirectory());
            _ValidMapStyles.AddRange(new GoogleMapStyles[] {GoogleMapStyles.RoadMap
                ,GoogleMapStyles.Satellite,GoogleMapStyles.Terrain });
        }//end method

        /// <summary>
        /// canvas大小改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void canvasMain_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            await DrawBackgroundAsync();
            await RefreshMapAsync();
            //RefreshMap(_ShowThumbnail);
        }//end method


        private async Task DrawBackgroundAsync()
        {
            if (IsShowScale)
            {
                await DrawScaleAsync();
            }
            else
            {
                canvasMain.Background = null;
            }
        }

        /// <summary>
        /// 画比例尺
        /// </summary>
        private async Task DrawScaleAsync()
        {
            await canvasMain.Dispatcher.InvokeAsync(delegate
            {
                int[] scales = new int[] { 10, 50, 100, 200, 500, 1000, 2000, 5000, 20000, 100000, 200000, 1000000, 5000000 };
                //int w = MapImageSize.Width;
                //int h = MapImageSize.Height;
                double w = this.canvasMain.ActualWidth;
                double h = this.canvasMain.ActualHeight;

                //计算屏幕点对应的距离
                double mx0, my0, mx1, my1, dx, dy;
                CoordinateTransform.PixelsToMeters(GeoCode.X, GeoCode.Y, ZoomLevel, out mx0, out my0);
                CoordinateTransform.PixelsToMeters(IsShowScale ? GeoCode.X + w - ScaleWidth : GeoCode.X + w
                    , IsShowScale ? GeoCode.Y - h - ScaleWidth : GeoCode.Y - h
                    , ZoomLevel, out mx1, out my1);
                dx = Math.Abs(mx0 - mx1);
                dy = Math.Abs(my0 - my1);

                int scale = 0;
                double totalX = 0;
                double totalY = 0;
                int max = (int)w / 60;
                int min = (int)w / 200;
                int offset = (int)ScaleWidth - 10;
                for (int i = 0; i < scales.Length; i++)
                {
                    totalX = dx / scales[i];
                    if (totalX >= min && totalX <= max)
                    {
                        scale = scales[i];
                        break;
                    }
                }

                if (scale > 0)
                {
                    totalY = (int)dy / scale;
#if DEBUG
                    Console.WriteLine("屏幕距离：{0} , {1} , 比例尺：{2}", dx, dy, scale);
#endif//DEBUG

                    //定义绘画对象及要使用的画刷画笔
                    DrawingVisual visual = new DrawingVisual();
                    //DrawingVisual visual = (this.canvasMain.Background as VisualBrush).Visual as DrawingVisual ;
                    DrawingContext context = visual.RenderOpen();
                    Brush backgroundBrush = ScaleBackground;
                    Brush foreBrush = ScaleForeground;
                    Pen forePen = new Pen(foreBrush, 0.6);
                    Typeface fontType = new Typeface("宋体");
                    double fontSize = 10.5;

                    //画出坐标系背景
                    Rect rect = new Rect(0, h - ScaleWidth, w, ScaleWidth);
                    context.DrawRectangle(backgroundBrush, null, rect);
                    rect = new Rect(0, 0, ScaleWidth, h);
                    context.DrawRectangle(backgroundBrush, null, rect);
                    //g.FillRectangle(brush, new Rectangle());
                    //g.FillRectangle(brush, new Rectangle(0, 0, ScaleWidth, h));

                    //画出坐标系的轴
                    //Pen pen = new Pen(ScaleForeColor);
                    context.DrawLine(forePen, new Point(offset, h - offset), new Point(w, h - offset));
                    context.DrawLine(forePen, new Point(offset, 0), new Point(offset, h - offset));

                    PathGeometry path = new PathGeometry(new PathFigure[] 
                {
                    new PathFigure(new Point(offset , 0) , new PathSegment[]
                    {
                        new LineSegment(new Point(ScaleWidth /2, 10) , false) ,
                        new LineSegment(new Point(offset + 5 , 10) , false)
                    } , true) 
                });
                    context.DrawGeometry(foreBrush, forePen, path);
                    path = new PathGeometry(new PathFigure[] 
                {
                    new PathFigure(new Point(w , h - offset) , new PathSegment[]
                    {
                        new LineSegment( new Point(w - 10 , h - offset) , false) ,
                        new LineSegment(new Point(w - 10 , h - offset -5) , false)
                    } , true) 
                });
                    context.DrawGeometry(foreBrush, forePen, path);

                    //写单位
                    string unitText = string.Format("单位({0})", scale >= 200 ? "公里" : "米");
                    FormattedText text = new FormattedText(unitText, CultureInfo.CurrentCulture
                        , System.Windows.FlowDirection.LeftToRight, fontType, fontSize, foreBrush);
                    context.DrawText(text, new Point(offset, h - offset + 2));
                    //Brush textBrush = new SolidBrush(ScaleForeColor);

                    //g.DrawString(unitText, font, textBrush, );

                    //画标尺
                    for (int i = 1; i < (int)totalX + 3; i++)
                    {
                        int x = (int)(w * i / totalX) + offset;
                        int y = (int)h - offset;
                        if (x > w - offset)
                        {
                            continue;
                        }
                        //画标尺
                        context.DrawLine(forePen, new Point(x, y), new Point(x, y - 10));

                        //画分割
                        for (int j = 1; j < 10; j++)
                        {
                            int x1 = x - (int)(w / totalX / 10 * j);
                            if (x1 > w - offset || x1 < offset)
                            {
                                continue;
                            }
                            context.DrawLine(forePen, new Point(x1, y), new Point(x1, y - 5));
                        }


                        //写字
                        double d = scale >= 200 ? i * (double)scale / 1000 : i * scale;

                        unitText = d - Math.Ceiling(d) != 0 ? string.Format("{0:N1}", d) : string.Format("{0:N0}", d);
                        //string text = string.Format("{0:N1}", scale >= 100 ? i * (float)scale / 1000 : scale);
                        text = new FormattedText(unitText, CultureInfo.CurrentCulture
                            , System.Windows.FlowDirection.LeftToRight, fontType, fontSize, foreBrush);
                        context.DrawText(text, new Point(x - fontSize / 2, y + 2));
                    }

                    //StringFormat format = new StringFormat(StringFormatFlags.DirectionVertical);
                    for (int i = 0; i < (int)totalY; i++)
                    {
                        int x = offset;
                        int y = (int)(h * ((int)totalY - i) / totalY) - offset;
                        context.DrawLine(forePen, new Point(x, y), new Point(x + 10, y));

                        //画分割
                        for (int j = 1; j < 10; j++)
                        {
                            int y1 = y - (int)(h / totalY / 10 * j) - 1;
                            context.DrawLine(forePen, new Point(x, y1), new Point(x + 5, y1));
                            if (y1 < offset * 2)
                            {
                                break;
                            }
                        }

                        //写字
                        double d = scale >= 200 ? i * (double)scale / 1000 : i * scale;
                        unitText = d - Math.Ceiling(d) != 0 ? string.Format("{0:N1}", d) : string.Format("{0:N0}", d);
                        text = new FormattedText(unitText, CultureInfo.CurrentCulture
                            , System.Windows.FlowDirection.LeftToRight, fontType, fontSize, foreBrush);
                        context.DrawText(text, new Point(2
                            , y - fontSize / 2));
                    }
                    context.Close();
                    gridMain.Background = new VisualBrush(visual);
                }
            });
        }//end method

        /// <summary>
        /// 刷新地图
        /// </summary>
        /// <returns></returns>
        private async Task RefreshMapAsync()
        {
            if (!this.IsLoaded)
            {
                return;
            }
            _IsMapLoaded = false;
            await canvasMain.Dispatcher.InvokeAsync(async delegate
            {
                //获得经纬度
                double lat = GeoCode.X;
                double lon = GeoCode.Y;
#if DEBUG
                Console.WriteLine("{0} , {1}", lat, lon);
#endif//DEBUG
                _MapImageSize = new Size(this.canvasMain.ActualWidth, this.canvasMain.ActualHeight);

                ////计算墨卡托坐标
                //计算像素坐标
                double px, py;
                CoordinateTransform.LatLonToPixels(lat, lon, ZoomLevel, out px, out py);

                int tx, ty;
                CoordinateTransform.PixelsToTile(px, py, out tx, out ty);

                int gx, gy;
                CoordinateTransform.GoogleTile(tx, ty, ZoomLevel, out gx, out gy);

                double minx, miny, maxx, maxy;
                CoordinateTransform.TileBounds(tx, ty, ZoomLevel, out minx, out miny, out maxx, out maxy);
                double minpx, minpy, maxpx, maxpy;
                CoordinateTransform.MetersToPixels(minx, miny, ZoomLevel, out minpx, out minpy);
                CoordinateTransform.MetersToPixels(maxx, maxy, ZoomLevel, out maxpx, out maxpy);

                //原点
                double oX = px - _MapImageSize.Width / 2;
                double oY = py + _MapImageSize.Height / 2;

                _GooglePoint = new Point((float)oX, (float)oY);


                int w = (int)this.canvasMain.ActualWidth;
                int h = (int)this.canvasMain.ActualHeight;

                //获得左上角及右下角坐标
                double left =  _GooglePoint.X;
                double top =  _GooglePoint.Y - h;
                double right = _GooglePoint.X + w;
                double bottom =  _GooglePoint.Y;
                CoordinateTransform.PixelsToLatLon(left, top, ZoomLevel, out lat, out lon);

                //
                //TODO:左上和右下的经纬度
                //
                //_LeftTopGeocode = string.Format("{0},{1}", lat, lon);
                //CoordinateTransform.PixelsToLatLon(right, bottom, _ZoomLevel, out lat, out lon);
                //_RightBottomGeocode = string.Format("{0},{1}", lat, lon);

                //
                //TODO:地图正在刷新事件
                //
                //CancelEventArgs ce = new CancelEventArgs(false);
                //OnMapRefreshing(ce);
                //if (ce.Cancel)
                //{
                //    return;
                //}



                //根据控件大小计算分块
                //int w = this.pbMain.Width  / 2;
                //int h = this.pbMain.Height / 2 ;
                int size = CoordinateTransform.TileSize;

                ///距离
                double offsetLeft = minpx - _GooglePoint.X;
                double offsetRight = _GooglePoint.X + _MapImageSize.Width - maxpx;
                double offsetTop = minpy - (_GooglePoint.Y - _MapImageSize.Height);
                double offsetBottom = _GooglePoint.Y - maxpy;

                //计算左上
                int w0 = (int)offsetLeft, h0 = (int)offsetTop;
                int x0 = w0 % size == 0 ? w0 / size : w0 / size + 1;
                int y0 = h0 % size == 0 ? h0 / size : h0 / size + 1;

                //计算右下
                int w1 = (int)offsetRight, h1 = (int)offsetBottom;
                int x1 = w1 % size == 0 ? w1 / size : w1 / size + 1;
                int y1 = h1 % size == 0 ? h1 / size : h1 / size + 1;


                //总共块数
                int x2 = x0 + x1 + 1;
                int y2 = y0 + y1 + 1;

                //所有的点
                int[] arrayX = new int[x0 + x1 + 2];
                int[] arrayY = new int[y0 + y1 + 2];
                for (int i = -x0; i < x1 + 2; i++)
                {
                    arrayX[i + x0] = w0 + size * i;

                }
                for (int i = -y1; i < y0 + 2; i++)
                {
                    arrayY[i + y1] = h1 + size * i;
                }

                Rect[,] rects = new Rect[x2, y2];

                //
                //TODO:计算要画的瓦片
                //
                List<DrawTileState> tempTiles = new List<DrawTileState>();
                List<DrawTileState> tempTiles1 = new List<DrawTileState>();
                for (int i = 0; i < x2; i++)
                {
                    for (int j = 0; j < y2; j++)
                    {
                        rects[i, j] = new Rect(arrayX[i], arrayY[j], size, size);
                        int gx1 = gx + i - x0;
                        int gy1 = gy + j - y1;

                        if (rects[i, j].Left < 0-CoordinateTransform.TileSize
                            || rects[i, j].Top < 0-CoordinateTransform.TileSize)
                        {
                            continue;
                        }
                        //
                        //TODO:根据地图类型，如果是hybird则需要同时取得卫星及hybrid两张瓦片
                        //
                        ////如果是hybrid则先取得卫星图片
                        //if (MapStyle == GoogleMapStyle.Hybrid)
                        //{
                        //    DrawTileState state1 = CreateTileState(gx1, gy1, rects[i, j], GoogleMapStyle.Satellite);
                        //    tempTiles1.Add(state1);
                        //}
                        //地图层
                        DrawTileState state = CreateTileState(gx1, gy1, rects[i, j], MapStyle);
                        tempTiles.Add(state);

                        //附加层
                        foreach (GoogleMapStyles mapStyle in AdditionalLayers)
                        {
                            DrawTileState state1 = CreateTileState(gx1, gy1, rects[i, j], mapStyle);
                            tempTiles.Add(state1);
                        }

                    }
                }

                //
                //TODO:移除超出范围的瓦片图形
                //
                List<Image> images = _States.Where(s => !tempTiles.Select(t => t.MapImage).Contains(s.MapImage))
                    .Select(s => s.MapImage).ToList();
                foreach (Image image in images)
                {
                    //image.Visibility = System.Windows.Visibility.Collapsed;
                    if (canvasMain.Children.Contains(image))
                    {
                        canvasMain.Children.Remove(image);
                    }
                }

                //如果超出缓存数量则移除前边的缓存图片
                if (MaxTileCacheCount > 0)  //如果是0则没有限制，否则限制缓存数量
                {
                    int i = 0;
                    while (_States.Count > MaxTileCacheCount - tempTiles.Count)
                    {
                        if (!tempTiles.Contains(_States[i]))
                        {
                            _States.RemoveAt(i);
                        }
                        else
                        {
                            i++;
                        }

                    }
                }
                //IEnumerable<Task> tasks1 = from state in tempTiles1 select DrawTileAsync(state);
                //await Task.WhenAll(tasks1);
                IEnumerable<Task> tasks = from state in tempTiles select DrawTileAsync(state);

                await Task.WhenAll(tasks);

            });

            _IsMapLoaded = true;

        }

        /// <summary>
        /// 创建瓦片state
        /// </summary>
        /// <param name="gx">谷歌瓦片x坐标</param>
        /// <param name="gy">谷歌瓦片y坐标</param>
        /// <param name="rect">瓦片的矩形区域</param>
        /// <returns></returns>
        private DrawTileState CreateTileState(int gx, int gy, Rect rect, GoogleMapStyles mapStyle)
        {
            DrawTileState state = _States.Where(d => d.GX == gx && d.GY == gy 
                && d.ZoomLevel == ZoomLevel 
                && d.MapStyle == mapStyle).FirstOrDefault();
            if (state == null)
            {
                state = new DrawTileState(gx, gy, rect, null, ZoomLevel, mapStyle, true);
                //string key = GetCachekey(state.ZoomLevel, state.GX, state.GY, state.MapStyle);
                Image image = new Image();
                
                image.Width = CoordinateTransform.TileSize;
                image.Height = CoordinateTransform.TileSize;
                state.MapImage = image;
                image.DataContext = state;
                this.canvasMain.Children.Add(image);
                _States.Add(state);
            }
            else
            {
                state.Rect = rect;
                state.NeedRedraw = false;

            }
            if (!this.canvasMain.Children.Contains(state.MapImage))
            {
                this.canvasMain.Children.Add(state.MapImage);
            }
            return state;
        }//end method


        /// <summary>
        /// 画瓦片
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        private async Task DrawTileAsync(DrawTileState state)
        {
            try
            {
                string url = Properties.Settings.Default.GoogleMap_Url_RoadMap;
                GoogleMapStyles mapStyle = state.MapStyle;
                switch (mapStyle)
                {
                    case GoogleMapStyles.RoadMap:
                        url = Properties.Settings.Default.GoogleMap_Url_RoadMap;
                        break;
                    case GoogleMapStyles.Satellite:
                        url = Properties.Settings.Default.GoogleMap_Url_Satellite;
                        break;
                    case GoogleMapStyles.Terrain:
                        url = Properties.Settings.Default.GoogleMap_Url_Terrain;
                        break;
                    case GoogleMapStyles.Text:
                        url = Properties.Settings.Default.GoogleMap_Url_Text;
                        break;
                    case GoogleMapStyles.Weather:
                        url = Properties.Settings.Default.GoogleMap_Url_Weather;
                        break;
                    case GoogleMapStyles.Traffic:
                        url = Properties.Settings.Default.GoogleMap_Url_Traffic;
                        break;
                    case GoogleMapStyles.Treasure:
                        url = Properties.Settings.Default.GoogleMap_Url_Treasure;
                        break;
                }
                //else if (MapStyle == GoogleMapStyle.Hybrid)
                //{
                //    url = Properties.Settings.Default.GoogleMap_Url_Text;
                //}

                url = string.Format(url, RandomGoogle(), state.GX, state.GY, state.ZoomLevel, RandomGoogle2());
                if (state.NeedRedraw)
                {
                    string fileName = GetCachekey(state.ZoomLevel, state.GX, state.GY, state.MapStyle);
                    
                    Uri uri = new Uri(url);
                    if (File.Exists(fileName))
                    {
                        uri = new Uri(fileName);
#if DEBUG
                        Console.WriteLine("获取本地瓦片：{0}", uri);
#endif//DEBUG
                    }
                    else if (!string.IsNullOrEmpty(fileName))
                    {
                        SaveCacheFileAsync(uri, fileName);
                    }
                    else
                    {
#if DEBUG
                        Console.WriteLine("获取远程瓦片：{0}", uri);
#endif//DEBUG

                    }
                    await state.MapImage.Dispatcher.InvokeAsync(delegate
                    {
                        //根据附加层不同改变显示顺序
                        Canvas.SetZIndex(state.MapImage,
                            AdditionalLayers.Contains(state.MapStyle)? 
                            100 + AdditionalLayers.IndexOf(state.MapStyle) : 90);
                        Canvas.SetLeft(state.MapImage, state.Rect.Left);
                        Canvas.SetTop(state.MapImage, state.Rect.Top);
                        BitmapImage bitmap = new BitmapImage(uri, _CachePolicy);
                        //bitmap.DownloadCompleted += bitmap_DownloadCompleted;
                        //BitmapImage bitmap = new BitmapImage(uri);
                        state.MapImage.Source = bitmap;

                    });
                }
                else
                {
                        Canvas.SetTop(state.MapImage, state.Rect.Top);
                        Canvas.SetLeft(state.MapImage, state.Rect.Left);
                        //Canvas.SetZIndex(state.MapImage, 0);
#if DEBUG
                        Console.WriteLine("移动瓦片从到({0})。",state.Rect);
#endif//DEBUG

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        private async void SaveCacheFileAsync(Uri uri, string fileName)
        {
            try
            {
                using (WebClient client = new WebClient())
                {
                    client.Headers.Add("User-Agent", WebClient_UserAgent);
                    byte[] buffer = await client.DownloadDataTaskAsync(uri);
                   
                    using (FileStream fs = new FileStream(fileName, FileMode.Create))
                    {
                        await fs.WriteAsync(buffer, 0, buffer.Length);
                        fs.Close();
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }//end method


        private void DoTileAnimation(Image image, Rect rect1, Rect rect2)
        {
            //await canvasMain.Dispatcher.InvokeAsync(delegate
            //{
                Storyboard storyboard = new Storyboard();

                //创建X轴方向动画

                DoubleAnimation doubleAnimation = new DoubleAnimation(

                  rect1.Left,

                  rect2.Left,

                  new Duration(TimeSpan.FromMilliseconds(500))

                );

                Storyboard.SetTarget(doubleAnimation, image);

                Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Left)"));

                storyboard.Children.Add(doubleAnimation);

                //创建Y轴方向动画

                doubleAnimation = new DoubleAnimation(

                  rect1.Top,

                  rect2.Top,

                  new Duration(TimeSpan.FromMilliseconds(500))

                );

                Storyboard.SetTarget(doubleAnimation, image);

                Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Top)"));

                storyboard.Children.Add(doubleAnimation);

                ////将动画动态加载进资源内

                //if (!Resources.Contains("rectAnimation"))
                //{

                //    Resources.Add("rectAnimation", storyboard);

                //}
                storyboard.Begin();
            //});
        }

        /// <summary>
        /// 获得缓存目录
        /// </summary>
        /// <returns></returns>
        private string GetCacheDirectory(int zoom, GoogleMapStyles mapStyle)
        {
            string directory = string.Empty;
            if (mapStyle == GoogleMapStyles.RoadMap)
            {
                directory = string.Format("{0}\\{1}x", _MapCacheDirectory, zoom);
            }
            else if (mapStyle == GoogleMapStyles.Satellite)
            {
                directory = string.Format("{0}\\s_{1}x", _MapCacheDirectory, zoom);
            }
            else if (mapStyle == GoogleMapStyles.Terrain)
            {
                directory = string.Format("{0}\\t_{1}x", _MapCacheDirectory, zoom);
            }
            else if (mapStyle == GoogleMapStyles.Text)
            {
                directory = string.Format("{0}\\h_{1}x", _MapCacheDirectory, zoom);
            }
            else if (mapStyle == GoogleMapStyles.Treasure)
            {
                directory = string.Format("{0}\\r_{1}x", _MapCacheDirectory, zoom);

            }

            try
            {
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }
            }
            catch { };

            return directory;
        }//end method

        /// <summary>
        /// 获得图片缓存键值
        /// </summary>
        /// <param name="zoom"></param>
        /// <param name="gx"></param>
        /// <param name="gy"></param>
        /// <returns></returns>
        private string GetCachekey(int zoom, int gx, int gy, GoogleMapStyles mapStyle)
        {
            if (mapStyle == GoogleMapStyles.RoadMap 
                || mapStyle == GoogleMapStyles.Satellite 
                || mapStyle == GoogleMapStyles.Terrain 
                || mapStyle == GoogleMapStyles.Text
                || mapStyle == GoogleMapStyles.Treasure)
            {
                string directory = GetCacheDirectory(zoom, mapStyle);
                string fileName = string.Format("{0}\\{1}-{2}.png", directory, gx, gy);
                return fileName;
            }
            else
            {
                return string.Empty;
            }

        }//end method

        /// <summary>
        /// 随机生成google地图服务器序号
        /// </summary>
        /// <returns></returns>
        private string RandomGoogle()
        {
            int ran = _random.Next(-1, 4);
            return ran.ToString().Replace("-1", "");
        }

        /// <summary>
        /// 随即生成google地图字符
        /// </summary>
        /// <returns></returns>
        private string RandomGoogle2()
        {
            string g = "Galileo";
            int ran = _random.Next(0, 7);
            string result = g.Substring(0, ran);
            result = string.IsNullOrEmpty(result) ? "G" : result;
            return result;
        }

        private async void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            await DrawBackgroundAsync();
            await RefreshMapAsync();
        }


        private  void sliderZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (_IsMapLoaded && (int)e.NewValue != (int)e.OldValue)
            {
                ZoomLevel = (int)e.NewValue;
                //await RefreshMapAsync();
            }
        }

        private void MapFunctionButton_TouchDown(object sender, TouchEventArgs e)
        {
            DoFunction(sender as Image, true);
        }
        private void MapFunctionButton_TouchUp(object sender, TouchEventArgs e)
        {
            
            DoFunction(sender as Image, false);
        }

        /// <summary>
        /// 导航按钮
        /// </summary>
        /// <param name="button"></param>
        private void DoFunction(Image button, bool isDown)
        {
            Trace.Assert(button != null, "图片按钮不应该为空。");

            //根据鼠标或者触摸按下抬起切换图片，用取巧替换图片文件名的方法，不是正规做法。
            string uri = button.Source.ToString();

            if (isDown)
            {
                button.Source = new BitmapImage(new Uri(uri.Replace("Normal", "Push")));
            }
            else
            {
                button.Source = new BitmapImage(new Uri(uri.Replace("Push", "Normal")));

            }

            //根据不同的按钮实现不同的功能
            if (!isDown)
            {
                if (button == btnZoomIn)   //放大地图比例
                {
                    if (sliderZoom.Value < sliderZoom.Maximum)
                    {
                        sliderZoom.Value += 1;
                    }
                }
                else if (button == btnZoomOut)   //缩小地图比例
                {
                    if (sliderZoom.Value > sliderZoom.Minimum)
                    {
                        sliderZoom.Value -= 1;
                    }
                }
                else
                {
                    if (this._IsMapLoaded)
                    {
                        Point centerPoint = new Point(_GooglePoint.X + _MapImageSize.Width / 2, _GooglePoint.Y - _MapImageSize.Height / 2);
                        if (button == btnLeft)
                        {
                            centerPoint = new Point(centerPoint.X - MovePixels, centerPoint.Y);
                        }
                        else if (button == btnRight)
                        {
                            centerPoint = new Point(centerPoint.X + MovePixels, centerPoint.Y);
                            //using (Graphics g = Graphics.FromImage(_Image))
                            //{
                            //    Point srcPoint = this.pbMain.PointToScreen(new Point(0, 0));
                            //    Point destPoint = new Point(srcPoint.X + 100, srcPoint.Y);
                            //    g.CopyFromScreen(srcPoint , destPoint , _Image.Size, CopyPixelOperation.SourceCopy);
                            //    return;
                            //}

                        }
                        else if (button == btnUp)
                        {
                            centerPoint = new Point(centerPoint.X, centerPoint.Y + MovePixels);

                        }
                        else if (button == btnDown)
                        {
                            centerPoint = new Point(centerPoint.X, centerPoint.Y - MovePixels);
                        }

                        double lat, lon;
                        CoordinateTransform.PixelsToLatLon(centerPoint.X, centerPoint.Y, ZoomLevel, out lat, out lon);
                        GeoCode = new Point(lat,lon);
                        //this.RefreshMap(true);
                    }

                }
            }
        }//end method

        private void MapFunctionButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 1)
            {
                DoFunction(sender as Image, true);
            }

        }
        private void MapFunctionButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 1)
            {
                DoFunction(sender as Image, false);
            }

        }

        private void UserControl_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (_IsMapLoaded)
            {
                if (e.Delta >= 120)
                {
                    if (sliderZoom.Value < sliderZoom.Maximum)
                    {
                        sliderZoom.Value += 1;
                    }
                }
                else
                {
                    if (sliderZoom.Value > sliderZoom.Minimum)
                    {
                        sliderZoom.Value -= 1;
                    }

                }
            }
        }

        /// <summary>
        /// 鼠标按钮抬起事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void canvasMain_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //如果是双击
            if(e.ClickCount == 1) //如果是按下
            {
                _LastPoint = e.MouseDevice.GetPosition(this.canvasMain);
            }
            else if (e.ClickCount == 2)
            {
                ZoomInAtPosition(e.MouseDevice.GetPosition(canvasMain));
            }

        }//end method

        private void ZoomInAtPosition(Point point)
        {
            int maxZoomLevel = GetMaxZoomLevel(MapStyle);
            if (ZoomLevel < maxZoomLevel)
            {
                //_GooglePoint = 
                double lat, lon;
                CoordinateTransform.PixelsToLatLon(_GooglePoint.X + point.X, _GooglePoint.Y - point.Y
    , ZoomLevel, out lat, out lon);
                GeoCode = new Point(lat, lon);
                ZoomLevel++;

            }
            //if(ZoomLevel <= 
        }//end method

        /// <summary>
        /// 获得最大缩放比率
        /// </summary>
        /// <returns></returns>
        private int GetMaxZoomLevel(GoogleMapStyles mapStyle)
        {
            int zoom = 20;

            if (mapStyle == GoogleMapStyles.Satellite)
            {
                zoom = 18;
            }
            else if (mapStyle == GoogleMapStyles.Terrain)
            {
                zoom = 15;
            }
            else if (mapStyle == GoogleMapStyles.RoadMap)
            {
                zoom = 17;
            }
            return zoom;
        }

        private void NavigateTo(Point point)
        {
            double offsetX = point.X - _LastPoint.X;
            double offsetY = point.Y - _LastPoint.Y;
#if DEBUG
            Console.WriteLine("拖动距离：x {0}, {1}", offsetX, offsetY);
#endif//DEBUG
            double lat = GeoCode.X;
            double lon = GeoCode.Y;
            double x, y;
            CoordinateTransform.LatLonToPixels(lat, lon, ZoomLevel, out x, out y);
            x = x - offsetX;
            y = y + offsetY;
            CoordinateTransform.PixelsToLatLon(x, y, ZoomLevel, out lat, out lon);
            GeoCode = new Point(lat, lon);

        }

        private void canvasMain_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point currentPoint = e.MouseDevice.GetPosition(canvasMain);
                Vector distance = currentPoint - _LastPoint;
                //if (distance.Length >= 10)
                //{
                    NavigateTo(currentPoint);
                    _LastPoint = currentPoint;
                //}
            }

        }//end method

    }//end class

    #region 辅助类

    #region 地图绘画状态类

    /// <summary>
    /// 地图状态类
    /// </summary>
    public class DrawTileState
    {
        /// <summary>
        /// 地图类型
        /// </summary>
        GoogleMapStyles _MapStyle;

        /// <summary>
        /// 设置或获得地图类型
        /// </summary>
        public GoogleMapStyles MapStyle
        {
            get
            {
                return _MapStyle;
            }
            set
            {
                _MapStyle = value;
            }
        }
        /// <summary>
        /// 缩放比率
        /// </summary>
        private int _ZoomLevel;

        /// <summary>
        /// 设置或获得缩放比率
        /// </summary>
        public int ZoomLevel
        {
            get
            {
                return _ZoomLevel;
            }
            set
            {
                _ZoomLevel = value;
            }

        }
        /// <summary>
        /// 要画的图像
        /// </summary>
        private Image _Image;

        /// <summary>
        /// 设置或获得要画的图像
        /// </summary>
        public Image MapImage
        {
            get
            {
                return _Image;
            }
            set
            {
                _Image = value;
            }
        }
        ///// <summary>
        ///// 手动信号
        ///// </summary>
        //ManualResetEvent _ManualEvent;

        ///// <summary>
        ///// 设置或获得手动信号
        ///// </summary>
        //public ManualResetEvent ManualEvent
        //{
        //    get
        //    {
        //        return _ManualEvent;
        //    }
        //    set
        //    {
        //        _ManualEvent = value;
        //    }
        //}

        /// <summary>
        /// 瓦片X坐标
        /// </summary>
        int _GX;

        /// <summary>
        /// 设置或获得瓦片X坐标
        /// </summary>
        public int GX
        {
            get
            {
                return _GX;
            }
            set
            {
                _GX = value;
            }
        }

        /// <summary>
        /// 瓦片Y坐标
        /// </summary>
        int _GY;

        public int GY
        {
            get
            {
                return _GY;
            }
            set
            {
                _GY = value;
            }
        }
        Rect _Rect;

        public Rect Rect
        {
            get
            {
                return _Rect;
            }
            set
            {
                _Rect = value;
            }
        }

        /// <summary>
        /// 是否需要重新画图
        /// </summary>
        bool _NeedRedraw = false;

        /// <summary>
        /// 设置或获得是否需要重新绘图
        /// </summary>
        public bool NeedRedraw
        {
            get { return _NeedRedraw; }
            set { _NeedRedraw = value; }
        }



        public DrawTileState()
        {
        }

        //public DrawTileState(int gx, int gy, Rectangle rect , ManualResetEvent manualEvent)
        //{
        //    _GX = gx;
        //    _GY = gy;
        //    _Rect = rect;
        //    _ManualEvent = manualEvent;
        //}

        public DrawTileState(int gx, int gy, Rect rect, Image image, int zoom, GoogleMapStyles mapStyle, bool needRedraw)
        {
            _GX = gx;
            _GY = gy;
            _Rect = rect;
            _Image = image;
            ZoomLevel = zoom;
            _MapStyle = mapStyle;
            _NeedRedraw = needRedraw;
        }

    }//end class 
    #endregion

    #region 地图标记事件及参数类

    /// <summary>
    /// 地图标记事件参数类
    /// </summary>
    public class MapMarkerEventArgs : System.EventArgs
    {
        /// <summary>
        /// 地图标记对象
        /// </summary>
        MapMarker _Marker;

        /// <summary>
        /// 设置或获得地图标记对象
        /// </summary>
        public MapMarker Marker
        {
            get
            {
                return _Marker;
            }
            set
            {
                _Marker = value;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public MapMarkerEventArgs()
        {
        }

        /// <summary>
        /// 重载构造函数
        /// </summary>
        /// <param name="marker"></param>
        public MapMarkerEventArgs(MapMarker marker)
        {
            _Marker = marker;
        }
    }//end method

    /// <summary>
    /// 地图标记委托
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void MapMarkerEventHandler(object sender, MapMarkerEventArgs e);

    /// <summary>
    /// 地图标记显示元素事件参数类
    /// </summary>
    public class MapMarkerUIElementEventArgs : MapMarkerEventArgs
    {
        /// <summary>
        /// 显示元素的热点，
        /// </summary>
        Point _HotSpot = new Point(0, 0);

        /// <summary>
        /// 获得或设置热点
        /// </summary>
        public Point HotSpot
        {
            get { return _HotSpot; }
            set { _HotSpot = value; }
        }

        /// <summary>
        /// 显示元素
        /// </summary>
        FrameworkElement _MarkerUIElement;

        /// <summary>
        /// 设置或获得显示元素
        /// </summary>
        public FrameworkElement MarkerUIElement
        {
            get { return _MarkerUIElement; }
            set { _MarkerUIElement = value; }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public MapMarkerUIElementEventArgs()
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="marker"></param>
        /// <param name="markerUIElement"></param>
        public MapMarkerUIElementEventArgs(MapMarker marker, FrameworkElement markerUIElement)
            : base(marker)
        {
            _MarkerUIElement = markerUIElement;
        }

        /// <summary>
        /// 改写构造函数
        /// </summary>
        /// <param name="marker"></param>
        /// <param name="markerUIElement"></param>
        /// <param name="hotSpot"></param>
        public MapMarkerUIElementEventArgs(MapMarker marker, FrameworkElement markerUIElement, Point hotSpot)
            : base(marker)
        {
            _MarkerUIElement = markerUIElement;
            _HotSpot = hotSpot;
        }

        public MapMarkerUIElementEventArgs(MapMarker marker)
            : base(marker)
        {
        }
    }//end class

    public delegate void MapMarkerUIElementEventHandler(object sender, MapMarkerUIElementEventArgs e);

    #endregion

    #region GeoCode类

    /// <summary>
    /// a class for latitude and longtitude
    /// </summary>
    [Serializable]
    public class GeoCode
    {
        /// <summary>
        /// latitude
        /// </summary>
        private string _latitude = string.Empty;

        /// <summary>
        /// longtitude
        /// </summary>
        private string _longtitude = string.Empty;

        /// <summary>
        /// default constructor
        /// </summary>
        public GeoCode()
        {

        }

        /// <summary>
        /// construct geo given latitude and longtitude
        /// </summary>
        /// <param name="latitude"></param>
        /// <param name="longtitude"></param>
        public GeoCode(string latitude, string longtitude)
        {
            _latitude = latitude;
            _longtitude = longtitude;
        }

        /// <summary>
        /// construct geo given name of a place
        /// </summary>
        /// <param name="location"></param>
        public GeoCode(string location)
        {
            //string output = "csv";
            //string url = string.Format(Properties.Settings.Default.GoogleGeoServer
            //    , location, output);
            //HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            //HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            //using (StreamReader sr = new StreamReader(response.GetResponseStream()))
            //{
            //    string[] tmpArray = sr.ReadToEnd().Split(',');
            //    if (tmpArray.Length == 2)
            //    {
            //        _latitude = tmpArray[2];
            //        _longtitude = tmpArray[3];
            //    }
            //    else
            //    {
            //        throw (new Exception("未取得指定地点的坐标。"));
            //    }
            //}
        }

        /// <summary>
        /// get latitude(纬度)
        /// </summary>
        public string Latitude
        {
            get { return _latitude; }
            set { _latitude = value; }
        }

        /// <summary>
        /// get longtitude(经度)
        /// </summary>
        public string Longtitude
        {
            get { return _longtitude; }
            set { _longtitude = value; }
        }

        public override string ToString()
        {
            return string.Format("{0},{1}", _latitude, _longtitude);
        }
    }//end class

    #endregion

    #region 地图类型枚举

    /// <summary>
    /// 地图类型
    /// </summary>
    public enum GoogleMapStyles
    {
        /// <summary>
        /// 卫星
        /// </summary>
        Satellite = 0,
        /// <summary>
        /// 地形
        /// </summary>
        Terrain,
        ///// <summary>
        ///// 混合
        ///// </summary>
        //Hybrid,
        /// <summary>
        /// 道路
        /// </summary>
        RoadMap,

        /// <summary>
        /// 文本标注
        /// </summary>
        Text,

        /// <summary>
        /// 交通
        /// </summary>
        Traffic,

        /// <summary>
        /// 天气
        /// </summary>
        Weather,

        /// <summary>
        /// 藏宝图
        /// </summary>
        Treasure


    }

    //public enum GoogleMapLayers
    //{
    //    Text,
    //    Traffic,
    //    Weather
    //}

    #endregion

    #region 地图模式枚举
    /// <summary>
    /// 地图模式
    /// </summary>
    public enum MapMode
    {
        /// <summary>
        /// 普通模式
        /// </summary>
        Normal,

        /// <summary>
        /// 测距模式
        /// </summary>
        CaculateDistance
    }//end enum


    #endregion

    #endregion

}//end namespacce
